#pragma once

// expansion macro for enum value definition
#define ENUM_VALUE(name, assign) name assign,

// expansion macro for enum to string conversion
#define ENUM_CASE(name, assign) \
    case name:                  \
        return #name;

// expansion macro for string to enum conversion
#define ENUM_STRCMP(name, assign) \
    if (!strcmp(str, #name))      \
        return name;

/// define the access function names
#define DEFINE_ENUM(EnumType, ENUM_DEF)                \
    enum EnumType                                      \
    {                                                  \
        ENUM_DEF(ENUM_VALUE)                           \
    };                                                 \
    const char *Get##EnumType##String(EnumType dummy); \
    EnumType Get##EnumType##Value(const char *string); \
    const char *Get##EnumType##String(EnumType value)  \
    {                                                  \
        switch (value)                                 \
        {                                              \
            ENUM_DEF(ENUM_CASE)                        \
        default:                                       \
            return ""; /* handle input error */        \
        }                                              \
    }                                                  \
    EnumType Get##EnumType##Value(const char *str)     \
    {                                                  \
        ENUM_DEF(ENUM_STRCMP)                          \
        return (EnumType)0; /* handle input error */   \
    }
